<?php
if(!defined('IN_IBEIKE')) {
	exit('Access Denied');
}

Class common_application extends common_base{
	public $mem;  //memcache对象
	public $session;//session对象
	public $config;//配置列表
	public $var;//对$_G的引用
	public $cachelist;//缓存列表
	public $init_db=true;
	public $init_setting=true;
	public $init_user=true;//user子函数初始化状态标志
	public $init_cron=true;
	public $init_session=true;//session子函数初始化状态标志
	public $init_misc=true;//misc子函数初始化状态标志
	public $initated=false; //初始化状态标志
	static function &instance(){
		static $object;
		if(empty($object)) {
			$object = new self();
		}
		return $object;
	}
	public function __construct(){
		$this->_init_env();
		$this->_init_config();
		$this->_init_input();
		$this->_init_output();
	}
	public function init(){
		if(!$this->initated) {
			$this->_init_db();
			$this->_init_setting();
			$this->_init_user();
			$this->_init_session();
			$this->_init_cron();
			$this->_init_misc();
		}
		$this->initated = true;
	}
	private function _init_env(){
		error_reporting(E_ERROR);
		define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
		define('ICONV_ENABLE', function_exists('iconv'));
		define('MB_ENABLE', function_exists('mb_convert_encoding'));
		define('EXT_OBGZIP', function_exists('ob_gzhandler'));		
		define('TIMESTAMP', time());
		date_default_timezone_get("Asia/Shanghai");
		include(DIR_ROOT.'./source/function/function_core.php');
		$memorylimit = ini_get('memory_limit');
			if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists('ini_set')) {
				ini_set('memory_limit', '128m');
			}
		
		define('IS_ROBOT', checkrobot());
		
		global $_G;
		$_G = array(
				'uid' => 0,
				'username' => '',
				'itoken' => '',
				'timestamp' => TIMESTAMP,
				'starttime' => microtime(true),
				'clientip' => $this->_get_client_ip(),
				'timenow' => array(),
				'siteurl' => '',
				'siteport' => '',
				'config' => array(),
				'setting' => array(),
				'user' => array(),
				'cookie' => array(),
				'style' => array(),
				'cache' => array(),
				'session' => array(),
		);
		$_G['basescript'] = CURSCRIPT;//脚本名称
		$_G['siteurl'] = dhtmlspecialchars('http://'.$_SERVER['HTTP_HOST'].$sitepath.'/');
		$url = parse_url($_G['siteurl']);
		$_G['siteroot'] = isset($url['path']) ? $url['path'] : '';
		$this->var = & $_G;
		
	}
	private function _init_input() {
		if (isset($_GET['GLOBALS']) ||isset($_POST['GLOBALS']) ||  isset($_COOKIE['GLOBALS']) || isset($_FILES['GLOBALS'])) {
			system_error('request_tainting');
		}
		if(MAGIC_QUOTES_GPC) {//预转义检测
			$_GET = dstripslashes($_GET);
			$_POST = dstripslashes($_POST);
			$_COOKIE = dstripslashes($_COOKIE);
		}
		$prelength = strlen($this->config['cookie']['cookiepre']);
		foreach($_COOKIE as $key => $val) {//转存cookie到$_G['cookie']
			if(substr($key, 0, $prelength) == $this->config['cookie']['cookiepre']) {
				$this->var['cookie'][substr($key, $prelength)] = $val;
			}
		}
		if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST)) {//合并参数
			$_GET = array_merge($_GET, $_POST);
		}
		if(isset($_GET['page'])) {
			$_GET['page'] = rawurlencode($_GET['page']);
		}
		$this->var['mod'] = empty($_GET['mod']) ? '' : dhtmlspecialchars($_GET['mod']);
		$this->var['inajax'] = $_SERVER['REQUEST_METHOD'] == 'GET' && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' || $_SERVER['REQUEST_METHOD'] == 'POST' ? 1 : 0;
		$this->var['page'] = empty($_GET['page']) ? 1 : max(1, intval($_GET['page']));
		$this->var['sid'] = $this->var['cookie']['sid'] = isset($this->var['cookie']['sid']) ? dhtmlspecialchars($this->var['cookie']['sid']) : '';
		$this->var['handlekey'] = !empty($_GET['handlekey']) && preg_match('/^\w+$/', $_GET['handlekey']) ? $_GET['handlekey'] : '';
		if(empty($this->var['cookie']['saltkey'])) {
			$this->var['cookie']['saltkey'] = random(8);
			dsetcookie('saltkey', $this->var['cookie']['saltkey'], 86400 * 30, 1, 1);
		}
		$this->var['authkey'] = md5($this->var['config']['security']['authkey'].$this->var['cookie']['saltkey']);
	}
	private function _init_output(){
		if($this->config['security']['urlxssdefend'] && $_SERVER['REQUEST_METHOD'] == 'GET' && !empty($_SERVER['REQUEST_URI'])) {
			$this->_xss_check();
		}
		if(!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false) {
			$this->config['output']['gzip'] = false;
		}
		$allowgzip = $this->config['output']['gzip'] && empty($this->var['inajax']) && $this->var['mod'] != 'attachment' && EXT_OBGZIP;
		setglobal('gzipcompress', $allowgzip);
		ob_start($allowgzip ? 'ob_gzhandler' : null);
		setglobal('charset', $this->config['output']['charset']);
		define('CHARSET', 'utf-8');
		if($this->config['output']['forceheader']) {
			@header('Content-Type: text/html; charset='.CHARSET);
		}
	}
	private function _init_config(){
		$_config = array();
		include DIR_ROOT.'./config/config_global.php';
		if(empty($_config['security']['authkey'])) {
			$_config['security']['authkey'] = md5($_config['cookie']['cookiepre'].$_config['db'][1]['dbname']);
		}
		//debug switch
		if(empty($_config['debug']) || !file_exists(libfile('function/debug'))) {
			define('IBEIKE_DEBUG', false);
			error_reporting(0);
		} elseif($_config['debug'] === 1 || $_config['debug'] === 2 || !empty($_REQUEST['debug']) && $_REQUEST['debug'] === $_config['debug']) {
			define('IBEIKE_DEBUG', true);
			error_reporting(E_ERROR);
			if($_config['debug'] === 2) {
				error_reporting(E_ALL);
			}
		} else {
			define('IBEIKE_DEBUG', false);
			error_reporting(0);
		}
		
		define('STATICURL', !empty($_config['output']['staticurl']) ? $_config['output']['staticurl'] : 'static/');
		$this->var['staticurl'] = STATICURL;
		
		$this->config = & $_config;
		$this->var['config'] = & $_config;
		
		if(substr($_config['cookie']['cookiepath'], 0, 1) != '/') {
			$this->var['config']['cookie']['cookiepath'] = '/'.$this->var['config']['cookie']['cookiepath'];
		}
		$this->var['config']['cookie']['cookiepre'] = $this->var['config']['cookie']['cookiepre'].substr(md5($this->var['config']['cookie']['cookiepath'].'|'.$this->var['config']['cookie']['cookiedomain']), 0, 4).'_';
		
		
	}
	public function reject_robot(){
		if(IS_ROBOT) {
			exit(header("HTTP/1.1 403 Forbidden"));
		}
	}
	private function _xss_check(){
		$temp = strtoupper(urldecode(urldecode($_SERVER['REQUEST_URI'])));
		if(strpos($temp, '<') !== false || strpos($temp, '"') !== false || strpos($temp, 'CONTENT-TRANSFER-ENCODING') !== false) {
			system_error('request_tainting');
		}
		return true;
	}
	private function _get_client_ip() {
		$ip = $_SERVER['REMOTE_ADDR'];
		if (isset($_SERVER['HTTP_X_REAL_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_FORWARDED_FOR'])) {
			$ip = $_SERVER['HTTP_X_REAL_FORWARDED_FOR'];
		}
		elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
			$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
		}
		elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		}
		return $ip;
	}
	private function _init_db(){
		$driver = 'db_mysql';
		DB::init($driver, $this->config['db']);
	}
	private function _init_session(){
		session_start();
		//TODO:即时SESSION与COOKIE结合
	}
	private function _init_user() {
		if($this->init_user) {
			if($auth = getglobal('auth', 'cookie')) {
				$auth = daddslashes(explode("\t", authcode($auth, 'DECODE')));
			}
			list($discuz_pw, $discuz_uid) = empty($auth) || count($auth) < 2 ? array('', '') : $auth;
			if($discuz_uid) {
				$user = getuserbyuid($discuz_uid, 1);
			}
			if(!empty($user) && $user['password'] == $discuz_pw) {
				$this->var['user'] = $user;
			} else {
				$user = array();
				$this->_init_guest();
			}
			//$this->cachelist[] = 'user_'.$this->var['user']['levelid'];//add to cachelist
		} else {
			$this->_init_guest();
		}
		if(empty($this->var['cookie']['lastvisit'])) {
			$this->var['user']['lastvisit'] = TIMESTAMP - 3600;
			dsetcookie('lastvisit', TIMESTAMP - 3600, 86400 * 30);
		} else {
			$this->var['user']['lastvisit'] = $this->var['cookie']['lastvisit'];
		}

		setglobal('uid', getglobal('uid', 'user'));
		setglobal('username', getglobal('username', 'user'));
		setglobal('levelid', getglobal('levelid', 'user'));
		//读取缓存
		//square
		!empty($this->cachelist) && loadcache($this->cachelist);
	}
	
	private function _init_guest(){
		setglobal('user', array( 'uid' => 0, 'username' => '', 'credits' => 0, 'timeoffset' => 9999));
	}
	private function _init_cron(){
		$ext = empty($this->config['remote']['on']) || empty($this->config['remote']['cron']) || APPTYPEID == 200;
		if($this->init_cron && $this->init_setting && $ext) {
			if($this->var['cache']['cronnextrun'] <= TIMESTAMP) {
				common_cron::run();
			}
		}
	}
	private function _init_misc(){
		if(!$this->init_misc) {
			return false;
		}
//		lang("core");
		if($this->init_setting && $this->init_user) {
			if(!isset($this->var['user']['timeoffset']) || $this->var['user']['timeoffset'] == 9999 || $this->var['member']['timeoffset'] === '') {
				$this->var['user']['timeoffset'] = $this->var['setting']['timeoffset'];
			}
		}
		$this->var['formhash'] = formhash();
		define('FORMHASH', $this->var['formhash']);
		if($this->init_user && $this->var['user']['uid'] != 0) {
			if($this->var['levelid']<1)			{
				showmessage('user_banned');
			}
		}
		
		if($this->var['setting']['ipaccess'] && !ipaccess($this->var['clientip'], $this->var['setting']['ipaccess'])) {
			showmessage('user_banned');
		}
		
		if($this->var['setting']['bbclosed']) {
			if($this->var['uid'] && $this->var['user']['levelid']== 255) {
			} elseif(in_array(CURSCRIPT, array('admin', 'member', 'api')) || defined('ALLOWGUEST') && ALLOWGUEST) {
			} else {
				$closedreason = C::t('common_setting')->fetch('closedreason');
				$closedreason = str_replace(':', '&#58;', $closedreason);
				showmessage($closedreason ? $closedreason : 'board_closed', NULL, array('adminemail' => $this->var['setting']['adminemail']), array('login' => 1));
			}
		}
		
		if(CURSCRIPT != 'admin' && !(in_array($this->var['mod'], array('logging', 'seccode')))) {
			periodscheck('visitbanperiods');
		}
		
		$this->var['tpp'] = $this->var['setting']['topicperpage'] ? intval($this->var['setting']['topicperpage']) : 20;
		$this->var['ppp'] = $this->var['setting']['postperpage'] ? intval($this->var['setting']['postperpage']) : 10;

		if($this->var['setting']['nocacheheaders']) {
			@header("Expires: -1");
			@header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
			@header("Pragma: no-cache");
		}
		
		if($this->session->isnew && $this->var['uid']) {
			//TODO:增加用户登录规则，统计
			
		}
		$lastact = TIMESTAMP."\t".dhtmlspecialchars(basename($this->var['PHP_SELF']))."\t".dhtmlspecialchars($this->var['mod']);
		dsetcookie('lastact', $lastact, 86400);
		setglobal('currenturl_encode', base64_encode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']));
		$this->var['seokeywords'] = !empty($this->var['setting']['seokeywords'][CURSCRIPT]) ? $this->var['setting']['seokeywords'][CURSCRIPT] : '';
		$this->var['seodescription'] = !empty($this->var['setting']['seodescription'][CURSCRIPT]) ? $this->var['setting']['seodescription'][CURSCRIPT] : '';
		
	}
	private function _init_setting(){
		if($this->init_setting) {
			if(empty($this->var['setting'])) {
				$this->cachelist[] = 'setting';
			}
		
			if(empty($this->var['style'])) {
				$this->cachelist[] = 'style_default';
			}
		
			if(!isset($this->var['cache']['cronnextrun'])) {
				$this->cachelist[] = 'cronnextrun';
			}
		}
		
		!empty($this->cachelist) && loadcache($this->cachelist);
		
		if(!is_array($this->var['setting'])) {
			$this->var['setting'] = array();
		}
	}
	public function _init_style(){
		define('IMGDIR', "./static/images");
		define('STYLEID',"1");
		define('VERHASH', "notmofidyed");
		define('TPLDIR', "./template");
		define('TEMPLATEID', "1");
	}
}
?>